1 /**
2  * Bellman-Ford path finding algorithm
3  *
4  * License:
5  *     D version of code is under MIT. The original is under Apache 2.0.
6  * 
7  *     The MIT License (MIT)
8  *
9  *     Copyright (c) 2014 Devisualization (Richard Andrew Cattermole)
10  *
11  *     Permission is hereby granted, free of charge, to any person obtaining a copy
12  *     of this software and associated documentation files (the "Software"), to deal
13  *     in the Software without restriction, including without limitation the rights
14  *     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  *     copies of the Software, and to permit persons to whom the Software is
16  *     furnished to do so, subject to the following conditions:
17  *
18  *     The above copyright notice and this permission notice shall be included in all
19  *     copies or substantial portions of the Software.
20  *
21  *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  *     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  *     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  *     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  *     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  *     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  *     SOFTWARE.
28  *
29  * See_Also:
30  *		http://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm
31  */
32 module devisualization.util.algorithms.pathfinding.bellmanford;
33 import devisualization.util.algorithms.pathfinding.defs;
34 deprecated("Killing"):
35 
36 /**
37  * Performs a Bellman-Ford search on a graph
38  *
39  * Params:
40  *     graph		=	The graph
41  *     source		=	The starting position
42  *     distance		=	Output: Distance between node and starting position
43  *     predecessor	=	Output: A node's previous node
44  */
45 void bellmanFord_search(T, U)(GridWithWeights graph, T source, out U[T] distance, out T[T] predecessor) {
46    // This implementation takes in a graph, represented as
47    // lists of vertices and edges, and fills two arrays
48    // (distance and predecessor) with shortest-path
49    // (less cost/distance/metric) information
50 
51    // Step 1: initialize graph
52 	foreach(k, v; graph.edges) {
53 		if (k == source)
54 			distance[k] = T.init;
55 		else
56 			static if (__traits(compiles, {T v = T.nan;}))
57 				distance[k] = T.nan;
58 			else
59 				distance[k] = T.max;
60        
61 		predecessor[k] = null;
62    }
63 
64     // Step 2: relax edges repeatedly
65     foreach(k, v; graph.edges) {
66 		foreach(v2; v) {
67 			auto w = graph.cost(k, v2);
68 			
69 			if (distance[u] + w < distance[v]) {
70 				distance[v] = distance[u] + w;
71 				predecessor[v] = u;
72 			}
73 		}
74     }
75 			   
76    // Step 3: check for negative-weight cycles
77    foreach(k, v; graph.edges) {
78 		foreach(v2; v) {
79 			auto w = graph.cost(k, v2);
80 			
81 			if (distance[u] + w < distance[v]) {
82 				throw new Exception("Graph contains a negative-weight cycle");
83 			}
84 		}
85    }
86 }